﻿using MicroMq.Services;

using Microsoft.Extensions.Logging;

using Peer;
using Peer.Define;

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MicroMq.Helper
{


    class MqConnectionManager
    {
        private readonly List<PeerConnection> connections = new List<PeerConnection>();

        private readonly ILogger<MqConnectionManager> logger;

        private readonly Dictionary<byte, IHandlerService> handlerServices;

        public MqConnectionManager(ILogger<MqConnectionManager> logger, IEnumerable<IHandlerService> handlerServices)
        {
            this.logger = logger;
            this.handlerServices = handlerServices.ToDictionary(a => a.HandleType, a => a);
        }

        internal void Accept(PeerStream e)
        {
            connections.Add(new PeerConnection(e));
            logger.LogInformation("连接接受，当前连接数：{0}", connections.Count);
            e.OnError += E_OnError;
            e.OnDisconnect += E_OnDisconnect;
            e.OnReceive += E_OnReceive;
        }

        internal PeerConnection Get(Guid guid)
        {
            return connections.FirstOrDefault(a => a.Guid == guid);
        }


        internal IPeerSession Group(string groupName)
        {
            return new PeerSession(connections, groupName);
        }

        private PeerResponse E_OnReceive(PeerStream peer, PeerRequest request)
        {
            var readBuffer = ByteReadBuffer.Wrap(StreamToBytes(request.Data));
            var type = readBuffer.ReadByte();
            if (!handlerServices.TryGetValue(type, out var handler))
                throw new InvalidOperationException();
            handler.Hanlder(Get(peer.Id), readBuffer);
            return request.CreateResponse();
        }

        private Span<byte> StreamToBytes(Stream stream)
        {
            if (stream is MemoryStream memoryStream)
            {
                return memoryStream.ToArray();
            }
            stream.Position = 0L;
            using MemoryStream memoryStream2 = new MemoryStream();
            stream.CopyTo(memoryStream2);
            return memoryStream2.ToArray();
        }

        private void E_OnDisconnect(object sender, PeerStream e)
        {
            Remove(e.Id);
            logger.LogInformation("连接断开，当前连接数：{0}", connections.Count);
            e.OnDisconnect -= E_OnDisconnect;
            e.OnError -= E_OnError;
            e.OnReceive -= E_OnReceive;
        }

        private void E_OnError(object sender, Exception e)
        {
            logger.LogError(e, "数据处理异常");
        }

        private void Remove(Guid guid)
        {
            connections.RemoveAll(a => a.Guid == guid);
        }
    }

}
